package com.whjfxx.terminal.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whjfxx.terminal.biz.enums.ResourceType;
import com.whjfxx.terminal.biz.enums.YesNoEnum;
import com.whjfxx.terminal.biz.mapper.ResourceMapper;
import com.whjfxx.terminal.biz.service.ResourceService;
import com.whjfxx.terminal.biz.vo.MenuInfoVo;
import com.whjfxx.terminal.biz.vo.MenuTreeVo;
import com.whjfxx.terminal.commons.Content;
import com.whjfxx.terminal.entity.Resource;
import com.whjfxx.terminal.entity.User;
import com.whjfxx.terminal.utils.RedisUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by b.c on 2022/4/14 10:23
 */
@Service
public class ResourceServiceImpl extends ServiceImpl<ResourceMapper, Resource> implements ResourceService {

    private void init() {

        String str = "";
        try {
            String path = "C:\\workspace1\\init.json";
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(path)), "UTF-8"));

            String lineTxt = "";

            while ((lineTxt = br.readLine()) != null) {
                str = str + lineTxt;
            }

            br.close();
        } catch (FileNotFoundException | UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (StringUtils.isBlank(str)) {
            return;
        }

        JSONObject jsonObject = JSONObject.parseObject(str);
        String homeInfoStr = jsonObject.getString("homeInfo");
        JSONObject homeInfo = JSONObject.parseObject(homeInfoStr);
        testSave(-1L, homeInfo, ResourceType.homeInfo);

        String logoInfoStr = jsonObject.getString("logoInfo");
        JSONObject logoInfo = JSONObject.parseObject(homeInfoStr);
        testSave(-1L, logoInfo, ResourceType.logoInfo);

        String menuInfo = jsonObject.getString("menuInfo");

        List<JSONObject> jsonObjects = JSONObject.parseArray(menuInfo, JSONObject.class);

        testS(-1L, jsonObjects, ResourceType.menu);

    }

    private void testS(Long pid, List<JSONObject> jsonObjects, ResourceType resourceType) {
        if (CollectionUtils.isEmpty(jsonObjects)) {
            return;
        }
        for (JSONObject jsonObject : jsonObjects) {
           Long parentId = testSave(pid, jsonObject, resourceType);

           String childStr = jsonObject.getString("child");
            List<JSONObject> childJsonObjects = JSONObject.parseArray(childStr, JSONObject.class);

            testS(parentId, childJsonObjects, resourceType);
        }
    }



    private Long testSave(Long pid,JSONObject jsonObject, ResourceType resourceType) {
        String title = jsonObject.getString("title");
        String href = jsonObject.getString("href");
        String icon = jsonObject.getString("icon");
        String target = jsonObject.getString("target");
        Resource resource = new Resource();

        resource.setTitle(title);
        resource.setHref(href);
        resource.setIcon(icon);
        resource.setTarget(target);

        resource.setShow(1);
        resource.setCreateTime(new Date());
        resource.setCreateUser(1L);
        resource.setUpdateTime(new Date());
        resource.setUpdateUser(1L);

        resource.setDeleted(0);
        resource.setType(resourceType.name());

        resource.setStatus(1);
        resource.setParentId(pid);
        this.save(resource);
        return resource.getId();
    }

    /**
     * 获取菜单
     * @param user
     * @return
     */
    @Override
    public MenuInfoVo getMenuInfoVo(User user) {
//        MenuInfoVo menuInfoVo = RedisUtil.hget(Content.RedisKeys.LOGIN_USER_MENU_HKEY, user.getId().toString());
//        if (Objects.nonNull(menuInfoVo)) {
//            return menuInfoVo;
//        }
        List<Resource> resources = getAll();
        if (CollectionUtils.isEmpty(resources)) {
            return null;
        }
        MenuInfoVo menuInfoVo = new MenuInfoVo();
        Iterator<Resource> iterator = resources.iterator();
        while(iterator.hasNext()) {
            Resource resource = iterator.next();
            // homeInfo
            if (ResourceType.homeInfo.name().equalsIgnoreCase(resource.getType())) {
                Map<String, Object> map = this.copy(resource, null);
                menuInfoVo.setHomeInfo(map);
                iterator.remove();
                continue;
            }
            // logoInfo
            else if (ResourceType.logoInfo.name().equalsIgnoreCase(resource.getType())) {
                Map<String, Object> map = this.copy(resource, null);
                menuInfoVo.setLogoInfo(map);

                iterator.remove();
                continue;
            }
        }
        List<Map<String, Object>> menuInfo = recursiveMenuTree1(Content.ROOT_PID, resources);
        menuInfoVo.setMenuInfo(menuInfo);
//        RedisUtil.hset(Content.RedisKeys.LOGIN_USER_MENU_HKEY, user.getId().toString(), menuInfoVo);
        return menuInfoVo;
    }

    @Override
    public List<Resource> getAll() {
        List<Resource> resources = RedisUtil.get(Content.RedisKeys.RESOURCE_KEY);
        if (CollectionUtils.isNotEmpty(resources)) {
            return resources;
        }
        LambdaQueryWrapper<Resource> wrapper = new LambdaQueryWrapper();
        wrapper.eq(Resource::getDeleted, YesNoEnum.NO.status);
        wrapper.orderByDesc(Resource::getSortId).orderByAsc(Resource::getId);
        resources = this.list(wrapper);
        if (CollectionUtils.isEmpty(resources)){
            init();
        }
        if (CollectionUtils.isNotEmpty(resources)) {
//            RedisUtil.set(Content.RedisKeys.RESOURCE_KEY, resources, 10);
        }
        return resources;
    }


    /**
     * 递归获取 获取树形结构数据
     * @param parentId
     * @param allResources
     * @return
     */
    private List<MenuTreeVo> recursiveMenuTree(Long parentId, List<Resource> allResources) {
        if (CollectionUtils.isEmpty(allResources) || null == parentId) {
            return null;
        }
        List<MenuTreeVo> menuTreeVos = new ArrayList<>();
        Iterator<Resource> iterator = allResources.iterator();
        while(iterator.hasNext()) {
            Resource resource = iterator.next();
            if (!parentId.equals(resource.getParentId())) {
                continue;
            }
            MenuTreeVo menuTreeVo = new MenuTreeVo();
            BeanUtils.copyProperties(resource, menuTreeVo);
            List<MenuTreeVo> child = recursiveMenuTree(menuTreeVo.getId(), allResources);
            if (CollectionUtils.isNotEmpty(child)) {
                menuTreeVo.setChild(child);
            }
            menuTreeVos.add(menuTreeVo);
        }
        return menuTreeVos;
    }


    /**
     * 递归获取 获取树形结构数据
     * @param parentId
     * @param allResources
     * @return
     */
    private List<Map<String, Object>> recursiveMenuTree1(Long parentId, List<Resource> allResources) {
        if (CollectionUtils.isEmpty(allResources) || null == parentId) {
            return null;
        }
        List<Map<String, Object>> menuTreeVos = new ArrayList<>();
        Iterator<Resource> iterator = allResources.iterator();
        while(iterator.hasNext()) {
            Resource resource = iterator.next();
            if (!parentId.equals(resource.getParentId())) {
                continue;
            }
            List<Map<String, Object>> child = recursiveMenuTree1(resource.getId(), allResources);
            Map<String, Object> map = this.copy(resource, child);
            menuTreeVos.add(map);
        }
        menuTreeVos = this.sort(menuTreeVos);
        return menuTreeVos;
    }

    /**
     * resource convert to map
     * @param resource
     * @param child
     * @return
     */
    private Map<String, Object> copy(Resource resource, List<Map<String, Object>> child) {
        Map<String, Object> map = new HashMap<>();
        map.put(Content.MenuKeys.title, resource.getTitle());
        map.put(Content.MenuKeys.icon, resource.getIcon());
        map.put(Content.MenuKeys.href, resource.getHref());
        map.put(Content.MenuKeys.sort, ObjectUtils.defaultIfNull(resource.getSortId(), 0));
        if (Objects.nonNull(resource.getTarget())) {
            map.put(Content.MenuKeys.target, resource.getTarget());
        }
        if (Objects.nonNull(resource.getImage())) {
            map.put(Content.MenuKeys.image, resource.getImage());
        }
        if (CollectionUtils.isNotEmpty(child)) {
            map.put(Content.MenuKeys.child, child);
        }
        return map;
    }

    /**
     * 根据sortId 倒序排序
     * @param menus
     */
    private List<Map<String, Object>> sort(List<Map<String, Object>> menus) {
        menus = menus.stream().sorted((a, b) -> Integer.compare((int)b.get(Content.MenuKeys.sort), (int) a.get(Content.MenuKeys.sort))).collect(Collectors.toList());
        return menus;
    }
}
